﻿using System;
using System.Collections.Generic;
using System.Text;

using System.Net;
using System.Net.Sockets;
using System.Runtime.InteropServices;
using System.Threading;

namespace NET_Server
{

    [StructLayout(LayoutKind.Sequential, Pack = 1)]
    //------------------------------------//
    //------ Struct for sending ----------//
    //------------------------------------//
    public struct ReciveData
    {

        public int count_player;
        public tplayer[] players;

        public byte[] ToBytes()
        {
            Byte[] bytes = new Byte[Marshal.SizeOf(typeof(ReciveData))];
            GCHandle pinStructure = GCHandle.Alloc(this, GCHandleType.Pinned);
            try
            {
                Marshal.Copy(pinStructure.AddrOfPinnedObject(), bytes, 0, bytes.Length);
                return bytes;
            }
            finally
            {
                pinStructure.Free();
            }
        }

    }
    [StructLayout(LayoutKind.Sequential, Pack = 1)]
    public struct SendData
    {
        public tplayer player;
        public byte[] ToBytes()
        {
            Byte[] bytes = new Byte[Marshal.SizeOf(typeof(ReciveData))];
            GCHandle pinStructure = GCHandle.Alloc(this, GCHandleType.Pinned);
            try
            {
                Marshal.Copy(pinStructure.AddrOfPinnedObject(), bytes, 0, bytes.Length);
                return bytes;
            }
            finally
            {
                pinStructure.Free();
            }
        }
    }
    [StructLayout(LayoutKind.Sequential, Pack = 1)]
    public struct tplayer
    {
        public Int32 ID_MD5;
        public Int32 x;
        public Int32 y;
        public Int32 bird;
    }

    public class CServer
    {
        public Socket Handle;
        public const int MAX_PLAYERS = 12;
        public int PlayersActiveCount = 0;
        public Socket[] PlayersSocketHandles = new Socket[MAX_PLAYERS];
        public bool[] PlayersActive = new bool[MAX_PLAYERS];
        public bool[] PlayersInitilized = new bool[MAX_PLAYERS];
        public int[] PlayersID = new int[MAX_PLAYERS];
        public bool Started = false;
        public SendData[] PlayersSendData = new SendData[MAX_PLAYERS];

        IPAddress ipAddr;
        IPEndPoint ipEndPoint;
        Socket sListener;


        Thread ListenThread;
        Thread[] PlayersThreads = new Thread[MAX_PLAYERS];

        public void Start(string addr)
        {
            ipAddr = IPAddress.Parse(addr);
            ipEndPoint = new IPEndPoint(ipAddr, 11000);
            sListener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            sListener.Bind(ipEndPoint);

            ListenThread = new Thread(new ThreadStart(ListenRoutine));
            ListenThread.Start();
            Started = true;

        }

        private void ListenRoutine()
        {
            while (true)
            {

                if (PlayersActiveCount < MAX_PLAYERS)
                {
                    sListener.Listen(10);
                    PlayersSocketHandles[PlayersActiveCount] = sListener.Accept();
                    //PlayersSocketHandles[PlayersActiveCount].Blocking = false;
                    PlayersActive[PlayersActiveCount] = true;
                    PlayersThreads[PlayersActiveCount] = new Thread(new ParameterizedThreadStart(PlayerRoutine));
                    PlayersThreads[PlayersActiveCount].Start(PlayersActiveCount);
                    PlayersActiveCount++;
                }
                else
                {
                    break;
                }
            }
        }

        private void PlayerRoutine(object obj)
        {
            int i = (obj as int);
            
            Socket PlayerSocket;

            lock (PlayersSocketHandles)
            {
                PlayerSocket = PlayersSocketHandles[i];
            }
            
            if (PlayerSocket != null) {
            while (PlayerSocket.Connected) 
            {
                // Получение данных от игрока
                byte[] inBuffer = new byte[Marshal.SizeOf(typeof(SendData))];

                PlayerSocket.Receive(inBuffer);
                SendData sd = new SendData();

                //public string ID_MD5;
                //public int x;
                //public int y;
                //public int bird;

                sd.player.ID_MD5 = BitConverter.ToInt32(inBuffer, 0);
                sd.player.x = BitConverter.ToInt32(inBuffer, 4);
                sd.player.y = BitConverter.ToInt32(inBuffer, 8);
                sd.player.bird = BitConverter.ToInt32(inBuffer, 12);

                // Запись полученных данных в общий массив
                lock (PlayersSendData[i]) 
                {
                    PlayersSendData[i] = sd;
                }

                // Собираем массив на отправку.
                ReciveData rd = new ReciveData();
                lock(PlayersSendData) {
                    for (int i = 0; i < MAX_PLAYERS; i++)
                    {
                        rd.count_player = PlayersActiveCount;
                        rd.players[i] = PlayersSendData[i];
                    }
                }

                // Отправка
                PlayerSocket.Receive(rd.ToBytes());

                //PlayerSocket.Send();
                
            
            }

            }

        }

        public void Shutdown()
        {

        }

    }
}
